#define DEBUG
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using ICSharpCode.TextEditor.Util;

namespace ICSharpCode.TextEditor.Document
{
	public sealed class LineSegment : ISegment
	{
		internal LineSegmentTree.Enumerator treeEntry;

		private int totalLength;

		private int delimiterLength;

		private List<TextWord> words;

		private SpanStack highlightSpanStack;

		private WeakCollection<TextAnchor> anchors;

		public bool IsDeleted => !this.treeEntry.IsValid;

		public int LineNumber => this.treeEntry.CurrentIndex;

		public int Offset => this.treeEntry.CurrentOffset;

		public int Length => this.totalLength - this.delimiterLength;

		int ISegment.Offset
		{
			get
			{
				return this.Offset;
			}
			set
			{
				throw new NotSupportedException();
			}
		}

		int ISegment.Length
		{
			get
			{
				return this.Length;
			}
			set
			{
				throw new NotSupportedException();
			}
		}

		public int TotalLength
		{
			get
			{
				return this.totalLength;
			}
			internal set
			{
				this.totalLength = value;
			}
		}

		public int DelimiterLength
		{
			get
			{
				return this.delimiterLength;
			}
			internal set
			{
				this.delimiterLength = value;
			}
		}

		public List<TextWord> Words
		{
			get
			{
				return this.words;
			}
			set
			{
				this.words = value;
			}
		}

		public SpanStack HighlightSpanStack
		{
			get
			{
				return this.highlightSpanStack;
			}
			set
			{
				this.highlightSpanStack = value;
			}
		}

		public TextWord GetWord(int column)
		{
			int num = 0;
			foreach (TextWord word in this.words)
			{
				if (column < num + word.Length)
				{
					return word;
				}
				num += word.Length;
			}
			return null;
		}

		public HighlightColor GetColorForPosition(int x)
		{
			if (this.Words != null)
			{
				int num = 0;
				foreach (TextWord word in this.Words)
				{
					if (x < num + word.Length)
					{
						return word.SyntaxColor;
					}
					num += word.Length;
				}
			}
			return new HighlightColor(Color.Black, bold: false, italic: false);
		}

		public override string ToString()
		{
			if (this.IsDeleted)
			{
				return "[LineSegment: (deleted) Length = " + this.Length + ", TotalLength = " + this.TotalLength + ", DelimiterLength = " + this.delimiterLength + "]";
			}
			return "[LineSegment: LineNumber=" + this.LineNumber + ", Offset = " + this.Offset + ", Length = " + this.Length + ", TotalLength = " + this.TotalLength + ", DelimiterLength = " + this.delimiterLength + "]";
		}

		public TextAnchor CreateAnchor(int column)
		{
			if (column < 0 || column > this.Length)
			{
				throw new ArgumentOutOfRangeException("column");
			}
			TextAnchor textAnchor = new TextAnchor(this, column);
			this.AddAnchor(textAnchor);
			return textAnchor;
		}

		private void AddAnchor(TextAnchor anchor)
		{
			Debug.Assert(anchor.Line == this);
			if (this.anchors == null)
			{
				this.anchors = new WeakCollection<TextAnchor>();
			}
			this.anchors.Add(anchor);
		}

		internal void Deleted(ref DeferredEventList deferredEventList)
		{
			this.treeEntry = LineSegmentTree.Enumerator.Invalid;
			if (this.anchors == null)
			{
				return;
			}
			foreach (TextAnchor anchor in this.anchors)
			{
				anchor.Delete(ref deferredEventList);
			}
			this.anchors = null;
		}

		internal void RemovedLinePart(ref DeferredEventList deferredEventList, int startColumn, int length)
		{
			if (length == 0)
			{
				return;
			}
			Debug.Assert(length > 0);
			if (this.anchors == null)
			{
				return;
			}
			List<TextAnchor> list = null;
			foreach (TextAnchor anchor in this.anchors)
			{
				if (anchor.ColumnNumber <= startColumn)
				{
					continue;
				}
				if (anchor.ColumnNumber >= startColumn + length)
				{
					anchor.ColumnNumber -= length;
					continue;
				}
				if (list == null)
				{
					list = new List<TextAnchor>();
				}
				anchor.Delete(ref deferredEventList);
				list.Add(anchor);
			}
			if (list == null)
			{
				return;
			}
			foreach (TextAnchor item in list)
			{
				this.anchors.Remove(item);
			}
		}

		internal void InsertedLinePart(int startColumn, int length)
		{
			if (length == 0)
			{
				return;
			}
			Debug.Assert(length > 0);
			if (this.anchors == null)
			{
				return;
			}
			foreach (TextAnchor anchor in this.anchors)
			{
				if ((anchor.MovementType == AnchorMovementType.BeforeInsertion) ? (anchor.ColumnNumber > startColumn) : (anchor.ColumnNumber >= startColumn))
				{
					anchor.ColumnNumber += length;
				}
			}
		}

		internal void MergedWith(LineSegment deletedLine, int firstLineLength)
		{
			if (deletedLine.anchors == null)
			{
				return;
			}
			foreach (TextAnchor anchor in deletedLine.anchors)
			{
				anchor.Line = this;
				this.AddAnchor(anchor);
				anchor.ColumnNumber += firstLineLength;
			}
			deletedLine.anchors = null;
		}

		internal void SplitTo(LineSegment followingLine)
		{
			if (this.anchors == null)
			{
				return;
			}
			List<TextAnchor> list = null;
			foreach (TextAnchor anchor in this.anchors)
			{
				if ((anchor.MovementType == AnchorMovementType.BeforeInsertion) ? (anchor.ColumnNumber > this.Length) : (anchor.ColumnNumber >= this.Length))
				{
					anchor.Line = followingLine;
					followingLine.AddAnchor(anchor);
					anchor.ColumnNumber -= this.Length;
					if (list == null)
					{
						list = new List<TextAnchor>();
					}
					list.Add(anchor);
				}
			}
			if (list == null)
			{
				return;
			}
			foreach (TextAnchor item in list)
			{
				this.anchors.Remove(item);
			}
		}
	}
}
